package pl.mmadej.ds4java.ds.common;

import java.util.Iterator;
import java.util.NoSuchElementException;

public abstract class BaseIterator<T> implements Iterator<T> {

    private LastIteratorAction lastIteratorAction = LastIteratorAction.NONE;

    private boolean lastIteratorActionWasRemoval() {
        return lastIteratorAction == LastIteratorAction.REMOVE;
    }

    protected abstract boolean walkingNotStarted();

    protected abstract boolean walkingEnded();

    protected enum LastIteratorAction {
        NONE, NEXT, REMOVE
    }

    @Override
    public T next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        lastIteratorAction = LastIteratorAction.NEXT;
        return doNext();
    }

    protected abstract T doNext();

    @Override
    public void remove() {
        if (walkingEnded()) {
            throw new IllegalStateException();
        }
        if (walkingNotStarted()) {
            throw new IllegalStateException();
        }
        if (lastIteratorActionWasRemoval()) {
            throw new IllegalStateException();
        }
        lastIteratorAction = LastIteratorAction.REMOVE;
        doRemove();
    }

    protected abstract void doRemove();
}
